<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>从化绿波-视频播放</title>
  <link href="../../css/index.css" rel="stylesheet">
  <style>
    .video-play {
      display: flex;
      width: 100%;
      height: 100%;
      box-sizing: border-box;
      padding-bottom: 0;
    }

    .video-list {
      flex: 0 0 120px;
      overflow: auto;
      padding: 10px;
      display: flex;
      flex-direction: column;
      overflow: hidden;
      background-color: #fff;
      margin-right: 10px;
      border-radius: 4px;
    }

    .search-list {
      margin-bottom: 10px;
    }

    .list-content {
      flex: 1;
      overflow: auto;
    }

    .list-content::-webkit-scrollbar {
      width: 0;
    }

    .play-list {
      flex: 1;
      display: grid;
      grid-template-columns: 50% 50%;
      grid-template-rows: 50% 50%;
      color: #ccc;
      font-size: 14px;
      height: 100%;
    }

    .play-item {
      border: 1px solid #ccc;
      background-color: #000;
      display: flex;
      align-items: center;
      justify-content: center;
      position: relative;
    }

    .video-item {
      width: 100%;
      height: 100%;
    }

    .device-item {
      cursor: pointer;
      padding: 10px 0;
      font-size: 12px;
    }

    .active {
      background-color: #ecf5ff;
      color: #409eff;
    }

    .item-title {
      background-color: rgba(0, 0, 0, 0.3);
      position: absolute;
      top: 0;
      right: 0;
      /* width: 100%; */
      padding: 4px 10px;
      box-sizing: border-box;
      display: flex;
      justify-content: space-between;
      color: #409eff;
      align-items: center;
      font-weight: 700;
    }

    .video-title {
      cursor: pointer;
    }

    img {
      width: 16px;
      cursor: pointer;
      margin-left: 10px;
    }
  </style>

</head>

<body>
  <div class="page-container" id="video-play">
    <div class="page-select">
      <div v-for="item in pageTab" @click="changeTab(item)" :key="item.key" class="select-item"
        :class="item.key === 'video-play' ? 'active-select': ''">
        {{item.label}}
      </div>
      <img class="login-out" src="../../assets/exit.png" alt="退出登录" title="退出登录" @click="handleLoginOut" />
    </div>
    <div class="iframe-container">
      <template v-if="alert.text">
        <div class="dialog-cover alert-dialog-cover"></div>
        <div class="alert-dialog dialog">
          <div class="dialog-title alert-dialog-title">
            提示
          </div>
          <div class="dialog-content">
            {{alert.text}}
          </div>
          <div class="dialog-footer alert-dialog-footer">
            <template v-if="alert.type === MESSAGE_TYPE.ALERT">
              <button class="primary-btn" @click="cancelConfirm">确定</button>
            </template>
            <template v-if="alert.type === MESSAGE_TYPE.CONFIRM">
              <button class="cancel-btn" @click="cancelConfirm">取消</button>
              <button class="primary-btn" @click="handleConfirm(alert)">确定</button>
            </template>
          </div>
        </div>
      </template>
      <div class="video-play">
        <div class="message" :class="message.type" v-if="message.text">{{message.text}}</div>
        <div class="video-list">
          <input class="search-list" v-model="videoSearch" style="width: 100%;" placeholder="路口" />
          <div class="list-content">
            <div v-for="item in searchList" :key="item.crossName">
              <div class="common-title video-title" @click="handlePlayAreaVideo(item)">{{item.crossName}}</div>
              <div v-for="child in item.devices" :key="child.ip" class="device-item"
                :class="activeItem(child) ? 'active' : ''" @click="handlePlayVideo(child, false)">
                {{child.name}}
              </div>
            </div>
          </div>
        </div>
        <div class="play-list">
          <div v-for="item in 4" class="play-item" :key="item">
            <video class="video-item" :id="`videoId_${item - 1}`" v-show="playList[item - 1]" autoplay muted playsinline
              controls></video>
            <div class="item-title" v-if="playList[item - 1]">
              <div>{{playList[item - 1]?.name}}</div>
              <img src="../../assets/guanbi-write.png" @click="handleClose(item - 1)" />
            </div>
            <div v-else class="tip">点击列表播放视频</div>
          </div>
        </div>
      </div>
    </div>
  </div>
</body>
<script src="../../js/vue3.js"></script>
<script src="../../config.js"></script>
<script src="../../js/method.js"></script>


<script>
  const { createApp, ref, nextTick, reactive, onMounted, onUnmounted, watch, computed } = Vue
  const app = createApp({
    setup() {
      const videoList = ref([])

      // 加载视频列表
      const loadVideoList = () => {
        fetch('../../js/dict/videoList.json')
          .then(res => res.json())
          .then(res => {
            console.log('videoList', res);
            videoList.value = res
          })
      }

      const videoSearch = ref()

      // 根据路口搜索视频
      const searchList = computed(() => {
        return videoSearch.value ? videoList.value.filter(item => item.crossName.indexOf(videoSearch.value) > -1) : videoList.value
      })

      let pcObj = {
        videoId_1: null,
        videoId_2: null,
        videoId_3: null,
        videoId_4: null
      }
      // 开始播放视频
      const startPlay = (id, ip) => {
        const videoEl = document.getElementById(id)
        if (!videoEl) { return }
        pcObj[id] = new RTCPeerConnection({
          // sdpSemantics: 'unified-plan'
        })
        pcObj[id].ontrack = function (event) {
          console.log(event.streams.length + ' track is delivered')
          videoEl.srcObject = event.streams[0]
          videoEl.play()
        }
        pcObj[id].addTransceiver('video', { direction: 'sendrecv' })
        pcObj[id].onnegotiationneeded = async function handleNegotiationNeeded() {
          const offer = await pcObj[id].createOffer()

          await pcObj[id].setLocalDescription(offer)
          const formData = new FormData()
          formData.append('data', btoa(pcObj[id].localDescription.sdp))
          const rtspUrl = videoUrl.replace('{camera_ip}', ip)
          fetch(rtspUrl, { method: 'POST', body: formData, })
            .then(res => res.text())
            .then((res) => {
              try {
                pcObj[id].setRemoteDescription(
                  new RTCSessionDescription({ type: 'answer', sdp: window.atob(res) })
                )
              } catch (e) {
                // console.warn(e)
              }
            }).catch((e) => {
              // console.log('ee', e)
              message.text = '无法播放视频'
              message.type = MESSAGE_TYPE.ERROR
              // errTip.value = '无法播放视频'
            })
        }

        const dc = pcObj[id]?.createDataChannel('rtsptowebSendChannel')
        dc.onopen = (event) => {
          console.log(`${dc.label} has opened`)
          dc.send('ping')
        }
        dc.onclose = (event) => {
          console.log(`${dc.label} has closed`)
          // startPlay(id, ip)
        }
        dc.onmessage = (event) => console.log(event.data)
      }

      // 关闭视频
      const close = (id) => {
        const idData = `videoId_${id}`
        console.log('pcObj[id]', pcObj, id, idData);
        pcObj[idData] && pcObj[idData]?.close()
        pcObj[idData] = null
        // errTip.value = ''
      }

      // 关闭全部视频
      const closeAll = () => {
        playList.value.forEach((item, index) => {
          item && close(index)
        })
      }

      // 是否激活栏
      const activeItem = computed(() => {
        return (item) => {
          const result = playList.value.find(ele => ele.ip === item.ip)
          return result
        }
      })

      const playList = ref(['', '', '', ''])

      // 点击视频播放
      const handlePlayVideo = (child, flag=true) => {
        // 如果视频已经在列表里面，那么就是取消播放
        const resultIndex = playList.value.findIndex(item => item.ip === child.ip)
        if (resultIndex !== -1) {
          playList.value[resultIndex] = ''
          close(resultIndex)
          return
        }
        // 如果有冗余的位置进行播放，那么就占用那个位置
        const index = playList.value.findIndex(item => !item)

        if (index === -1) {
          message.text = '最多可播放四个视频'
          message.type = MESSAGE_TYPE.ALERT
          return
        }
        playList.value[index] = child
        startPlay(`videoId_${index}`, child.ip)
      }

      const currentSite = ref('')
      // 点击路口播放当前路口所有视频
      const handlePlayAreaVideo = async (item) => {  
        await closeAll()
        if (Number(currentSite.value) === Number(item.crossNo)) {
          currentSite.value = ''
          // playList.value = ['', '', '', '']
          playList.value.forEach((playItem, playIndex) => {
            if (item.devices.find(ele => ele.ip === playItem.ip)) {
              playList.value[playIndex] = ''
            }
          })
          return
        }
        currentSite.value = item.crossNo
        setTimeout(() => {
          playList.value = ['', '', '', '']
          item.devices.forEach(ele => {
            handlePlayVideo(ele)
          })
        }, 5)

      }

      const MESSAGE_TYPE = {
        'SUCCESS': 'success',
        'INFO': 'info',
        'ALERT': 'alert',
        'ERROR': 'error',
        'CONFIRM': 'confirm'
      }

      const message = reactive({
        type: '',
        text: ''
      })

      const alert = reactive({
        type: '',
        text: '',
        methods: '',
        item: ''
      })

      // 弹窗消息1.5秒消失
      watch(
        () => message.text,
        () => {
          if (message.text) {
            setTimeout(() => {
              message.text = ''
            }, 2000)
          }
        }
      )

      const cancelConfirm = () => {
        alert.type = ''
        alert.text = ''
        alert.methods = ''
        alert.item = ''
      }

      // 确认操作
      const handleConfirm = async (alert) => {
        try {
          await methodsList[alert.methods](alert.item)
          cancelConfirm()
        } catch {
          cancelConfirm()
        }
      }

      const handleLoginOut = () => {
        alert.text = `确定退出登录吗?`
        alert.type = MESSAGE_TYPE.CONFIRM
        alert.methods = 'goLogin'
      }

      const methodsList = {
        'goLogin': goLogin,
      }

      // 点击视频名称 关闭视频
      const handleClose = (index) => {
        playList.value[index] = ''
        close(index)
      }

      onMounted(() => {
        hasLogin(apiUrl)
        loadVideoList()
      })

      onUnmounted(() => {
        closeAll()
      })
      return {
        videoList,
        videoSearch,
        searchList,
        playList,
        activeItem,
        message,
        pageTab,
        changeTab,
        alert,
        MESSAGE_TYPE,
        cancelConfirm,
        handleLoginOut,
        handleConfirm,
        handlePlayVideo,
        handleClose,
        handlePlayAreaVideo
      }
    },
  })
  app.mount('#video-play')
</script>

</html>